package com.sky.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.entity.DishFlavor;
import com.sky.entity.Setmeal;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.mapper.DishFlavorMapper;
import com.sky.mapper.DishMapper;
import com.sky.mapper.SetmealDishMapper;
import com.sky.mapper.SetmealMapper;
import com.sky.result.PageResult;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class DishServiceImpl implements DishService {
   @Autowired
   private DishMapper dishMapper;//菜品mapper
   @Autowired
   private DishFlavorMapper dishFlavorMapper;//菜品口味mapper
   @Autowired
   private SetmealMapper setmealMapper;//菜品mapper
   @Autowired
   private SetmealDishMapper setmealDishMapper;

   @Override
   @Transactional//添加事务控制
   public void save(DishDTO dishDTO) {
      log.info("菜品基本信息添加菜品表");
      //1:菜品基本数据存到菜品表
      Dish dish = new Dish();
      //dish数据来源于 dishDTO
      BeanUtils.copyProperties(dishDTO,dish);
      //公共字段已经填充了。。。
      dishMapper.insert(dish);//添加到了 菜品表中了  要主键回显



      log.info("菜品口味信息添加口味表");
      //2:口味信息存到口味表
      List<DishFlavor> flavors = dishDTO.getFlavors();//获取口味列表

      if(flavors==null||flavors.size()==0){//没有口味
         return;//就不用口味表加数据
      }

      //口味表中每个口味都没有 dish_id 因为前端没传递 因为不能传递 那是数据自增的。。。。
      for (DishFlavor flavor : flavors) {
//         flavor.setDishId(菜品id?来自dish?主键回显?菜品id与菜品添加 主键的回显);
           flavor.setDishId(dish.getId());
      }

      dishFlavorMapper.insertBatch(flavors);
   }

   /**
    * 分页查询
    * @param dishPageQueryDTO
    * @return
    */
   @Override
   public PageResult page(DishPageQueryDTO dishPageQueryDTO) {
      // 把五个参数获取出来了
      int page = dishPageQueryDTO.getPage();
      int pageSize = dishPageQueryDTO.getPageSize();
      String name = dishPageQueryDTO.getName();
      Integer categoryId = dishPageQueryDTO.getCategoryId();
      Integer status = dishPageQueryDTO.getStatus();
      //使用插件完成
      PageHelper.startPage(page,pageSize);
      //调用mapper方法
//      Page<DishVO> p = dishMapper.list(name,categoryId,status);
      Page<DishVO> p = dishMapper.list(dishPageQueryDTO);
      return new PageResult(p.getTotal(),p.getResult());
   }

   /**
    *  涉及到三张表
    *       三个Mapper
    *       多条sql 就用事务
    * @param ids
    */
   @Override
   @Transactional
   public void deleteBatch(List<Long> ids) {
      // 启售的菜品不能删除  -- 只要多个菜品中 有菜品的状态是1就不能删除
      // 国静的想法  根据id查询每个菜品 查看状态 如果有启售的就抛出异常不能删除
      //  select * from dish where id = ?
      for (Long id : ids) {//获取到每个id
         //根据id查询
         Dish dish = dishMapper.getById(id);
         // if(dish.getStatus()== 1){
         if(dish.getStatus()== StatusConstant.ENABLE){
            throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
            //以后是自己定义 异常和常量是开发过程中自己定义
         }
      }
      // 我的想法 select count(*) from dish where status=1 and id in(?,?,?)
      //  数量>0 说明有 就抛出异常

      // 被套餐关联的 菜品 不能删除
      // 怎么知道被套餐管理了？  根据菜品id 查询有没有管理的 套餐id 有就不能删除
      // select setmeal_id from setmel_dish where dish_id in(?,?,?)
      //  查询结果  0 个 1个 2个 3 个......  List<Long>
      List<Long> setmealIds = setmealDishMapper.getSetmealIdsByDishId(ids);
      if(setmealIds!=null && setmealIds.size()>0){//判断管理套餐的数量 有就不能 没有就可以删除
         throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
         //以后是自己定义 异常和常量是开发过程中自己定义
      }
      // 如果能删除 还得删除关联的口味
      for (Long id : ids) {//每一个菜品id
         dishMapper.deleteById(id);//根据菜品id删除菜品
         dishFlavorMapper.deleteByDishId(id);//根据菜品id进行删除口味信息
      }

   }

   /**
    *  根据菜品id 查询菜品信息 并封装DishVo
    * @param id
    * @return
    */
   @Override
   public DishVO getByIdWithFlavor(Long id) {
      // 根据菜品id 查询菜品基本信息
      Dish dish = dishMapper.getById(id);
      // 根据菜品id 查询菜品口味信息
      List<DishFlavor> dishFlavors = dishFlavorMapper.getByDishId(id);

      // 封装 DishVo
      DishVO dishVO = new DishVO();
      BeanUtils.copyProperties(dish,dishVO);
      dishVO.setFlavors(dishFlavors);

      return dishVO;
   }
  /*
    修改菜品信息
   */
   @Override
   public void update(DishDTO dishDTO) {
        // 修改菜品基本数据
      Dish dish = new Dish();
      BeanUtils.copyProperties(dishDTO,dish);
      dishMapper.update(dish);

       // 修改菜品关联口味数据
      //  删除关系 重新构建
      dishFlavorMapper.deleteByDishId(dish.getId());//根据菜品id进行删除口味信息
      // 添加
      // 口味信息存到口味表
      List<DishFlavor> flavors = dishDTO.getFlavors();//获取口味列表

      if(flavors==null||flavors.size()==0){//没有口味
         return;//就不用口味表加数据
      }

      //口味表中每个口味都没有 dish_id 因为前端没传递 因为不能传递 那是数据自增的。。。。
      for (DishFlavor flavor : flavors) {
//         flavor.setDishId(菜品id?来自dish?主键回显?菜品id与菜品添加 主键的回显);
         flavor.setDishId(dish.getId());
      }

      dishFlavorMapper.insertBatch(flavors);
   }

   /**
    * 根据分类id查询菜品
    * @param categoryId
    * @return
    */
   public List<Dish> list(Long categoryId) {
      Dish dish = Dish.builder()
              .categoryId(categoryId)
              .status(StatusConstant.ENABLE)
              .build();
      return dishMapper.dishList(dish);
   }

   /**
    * 条件查询菜品和口味
    * @param dish
    * @return
    */
   public List<DishVO> listWithFlavor(Dish dish) {
      List<Dish> dishList = dishMapper.dishList(dish);

      List<DishVO> dishVOList = new ArrayList<>();

      for (Dish d : dishList) {
         DishVO dishVO = new DishVO();
         BeanUtils.copyProperties(d,dishVO);

         //根据菜品id查询对应的口味
         List<DishFlavor> flavors = dishFlavorMapper.getByDishId(d.getId());

         dishVO.setFlavors(flavors);
         dishVOList.add(dishVO);
      }

      return dishVOList;
   }

   /**
    * 菜品起售停售
    *
    * @param status
    * @param id
    */
   @Transactional
   public void startOrStop(Integer status, Long id) {
      Dish dish = Dish.builder()
              .id(id)
              .status(status)
              .build();
      dishMapper.update(dish);

      if (status == StatusConstant.DISABLE) {
         // 如果是停售操作，还需要将包含当前菜品的套餐也停售
         List<Long> dishIds = new ArrayList<>();
         dishIds.add(id);
         // select setmeal_id from setmeal_dish where dish_id in (?,?,?)
         List<Long> setmealIds = setmealDishMapper.getSetmealIdsByDishId(dishIds);
         if (setmealIds != null && setmealIds.size() > 0) {
            for (Long setmealId : setmealIds) {
               Setmeal setmeal = Setmeal.builder()
                       .id(setmealId)
                       .status(StatusConstant.DISABLE)
                       .build();
               setmealMapper.update(setmeal);
            }
         }
      }
   }
}
